// 创建项目,拉取模版
const axios = require("axios");
const Inquirer = require("inquirer"); //命令交互
const path = require("path");
const {promisify} = require("util");
const downloadGitRepo = promisify(require("./download-git-repo.js")); //下载项目用的
const Metalsmith = require("metalsmith"); //用来遍历文件的
const { render } = require("consolidate").ejs;
const consolidateRender = promisify(render); //用来处理ejs模版的，替换需要填写的内容
const fs = require("fs");
const { loadingFn, figletFn, downloadDirectory, copyFile, checkFile, deleteFolderRecursive } = require("./utils");
const ApiConfig = require("./apiConfig.js")
/**
 * 获取可选择的模版信息
 * @returns 
 */
const getList = async ()=>{
    // const {data} = await axios.get("https://api.github.com/orgs/td-cli/repos")
    const {data} = await axios.get(ApiConfig.getListUrl())
    return data;
}
/**
 * 获取版本号
 * @param {名字 string} repo 
 * @returns 
 */
const getTags = async (repo)=>{
    // const {data} = await axios.get(`https://api.github.com/repos/td-cli/${repo}/tags`)
    const {data} = await axios.get(ApiConfig.getTagsUrl(repo))
    
    return data;
}
/**
 * 下载模版
 * @param {模版名字} repo 
 * @param {版本号} tag 
 * @param {是否强制覆盖} force 
 * @returns 
 */
const downloadFn = async (repo,tag,force)=>{
    const api = ApiConfig.getDownUrl(repo,tag);
    const dest = `${downloadDirectory}/${repo}/${tag||'.default'}`
    if(fs.existsSync(dest)){ //如果缓存里面有
        if(force){ //强制覆盖就需要先删除
            deleteFolderRecursive(dest)
        }else{ //直接返回路径，不需要去下载
            return dest;
        }
    }
    await downloadGitRepo(api,dest, { clone: ApiConfig.clone });
    return dest;
}
module.exports = async (option,projectName)=>{
    const url = path.join(process.cwd(),projectName); //当前工作路径拼上项目名字
    await checkFile(url,option.force); //检查文件是否存在
    const template = await loadingFn(getList,"fetch template...")(); //获取模版信息
    const { repo } = await Inquirer.prompt({
        name:"repo", //选择后的结果
        message:"请选择模版创建项目", //提示信息
        type:"list", //什么方式展示，单选
        choices:template.map(item=>item.name), //选择的数据

        // type:"checkbox", //多选
        // choices:[
        //     {
        //         name:'ts',
        //         checked:'true'
        //     },{
        //         name:'vuex'
        //     }
        // ], //选择的数据
    })
    const tags = await loadingFn(getTags,"fetch tags...")(repo); //获取版本号
    const { tag } = await Inquirer.prompt({
        name:"tag", //选择后的结果
        message:"请选择模版的版本号", //提示信息
        type:"list", //什么方式展示，单选
        choices:tags.map(item=>item.name), //选择的数据
    })
    const result = await loadingFn(downloadFn,"download tempatle...")(repo,tag,option.force); //下载模版
    const configFile = ApiConfig.getConfigFile(); //获取配置文件
    const filePath = path.join(result,configFile);
    if(!configFile || !fs.existsSync(filePath)){ // 不需要用户输入的配置的，直接复制过来
        await copyFile(result,projectName)
    }else{ //需要替换模版文字的
        await new Promise((resolve,reject)=>{
            //遍历文件
            Metalsmith(__dirname)
            .source(result)
            .destination(path.resolve(projectName))
            .use(async (files,metal, next)=>{ // 交互信息，获取交互填写后的结果
                const args = require(filePath);
                const obj = await Inquirer.prompt(args); // 让用户填写信息
                const meta = metal.metadata(); //获取携带的参数
                Object.assign(meta,obj); //将参数合并，下面个use去处理
                delete files[configFile]; //删除文件
                next();
            })
            .use(async (files,metal, next)=>{ //处理模版，替换
                const meta = metal.metadata();
                Reflect.ownKeys(files).forEach(async file=>{
                    if(file.endsWith('.js') || file.endsWith('.json')){ //需要替换的文件
                        const content = files[file].contents.toString(); //文件内容
                        if(content.includes("<%")){ //有需要替换的模版值
                            const buffer = await consolidateRender(content,meta); //替换模版中的值
                            files[file].contents = Buffer.from(buffer); //重新赋值
                        }
                    }
                })
                next();
            })
            .build(err=>{
                if(err){
                    reject()
                }else{
                    resolve();
                }
            })
        })
    }
    // 打印图形文字
    figletFn("cyj");
}